package com.gtmc.gclub.chat.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gtmc.gclub.chat.bean.Result;
import com.gtmc.gclub.chat.constants.ChatConstant;
import com.gtmc.gclub.chat.constants.ChatErrorCode;
import com.gtmc.gclub.chat.constants.CommonProperties;
import com.gtmc.gclub.chat.dao.TmPotentialUserMapper;
import com.gtmc.gclub.chat.dao.TrUserEnterpriseMapper;
import com.gtmc.gclub.chat.dao.WxChatLogMapper;
import com.gtmc.gclub.chat.dao.WxUserOwnerMapper;
import com.gtmc.gclub.chat.dto.ChatMsgDetailDto;
import com.gtmc.gclub.chat.dto.WxGzMessageDto;
import com.gtmc.gclub.chat.jmessage.UserOperator;
import com.gtmc.gclub.chat.model.TmCarOwner;
import com.gtmc.gclub.chat.model.TmDealer;
import com.gtmc.gclub.chat.model.TmPotentialUser;
import com.gtmc.gclub.chat.model.TrUserEnterprise;
import com.gtmc.gclub.chat.model.WxToken;
import com.gtmc.gclub.chat.model.WxUserOwner;
import com.gtmc.gclub.chat.policy.ChatPolicy;
import com.gtmc.gclub.chat.service.ChatWaitQueueService;
import com.gtmc.gclub.chat.service.DataCollectService;
import com.gtmc.gclub.chat.service.DealerService;
import com.gtmc.gclub.chat.service.MessageService;
import com.gtmc.gclub.chat.service.OwnerService;
import com.gtmc.gclub.chat.service.WxChatUserService;
import com.gtmc.gclub.chat.service.WxService;
import com.gtmc.gclub.chat.service.WxUserService;
import com.gtmc.gclub.chat.util.DateUtil;
import com.gtmc.gclub.chat.util.MessageOperate;
import com.gtmc.gclub.chat.util.RandomNum;
import com.gtmc.gclub.common.WxMaterialTypeEnum;
import com.gtmc.gclub.common.WxMediaFileSourceType;
import com.gtmc.gclub.common.WxUtil;
import com.gtmc.gclub.wx.dto.WxMsgSend;
import com.infoservice.filestore.FileStore;
import com.infoservice.filestore.FileStoreException;

import io.swagger.annotations.ApiOperation;

@Controller
@RequestMapping(value = "/chat")
public class ChatController extends BaseController {

	@Autowired
	private WxChatUserService wxChatUserService;

	@Autowired
	private DealerService dealerService;

	@Autowired
	private MessageService messageService;

	@Autowired
	private OwnerService ownerService;

	@Autowired
	private WxService wxService;

	@Autowired
	private WxUserService wxUserService;

//	@Autowired
//	private DataCollectService dataCollectService;

	@Autowired
	private UserOperator userOperator;

	@Autowired
	private CommonProperties commonProperties;

	@Autowired
	private TrUserEnterpriseMapper wxChatUserMapper;
	
	@Autowired
	private WxUserOwnerMapper wxUserOwnerMapper;

	@Autowired
	private WxChatLogMapper wxChatLogMapper;
	
	@Autowired
	private TmPotentialUserMapper tmPotentialUserMapper;
	
	@Autowired
	private TrUserEnterpriseMapper trUserEnterpriseMapper;
	
	@Autowired
	private WxController wxController;
	
	private ChatWaitQueueService queueService = ChatWaitQueueService.newInstance();

	@ResponseBody
	@RequestMapping(value = "/wx/users", method = { RequestMethod.GET })
	@ApiOperation(value = "查询客服列表", notes = "查询一个销售店的客服列表")
	public Result<List> wxUserList(@RequestParam(value = "code", required = true) String code) {
		// 获取该销售店所有客服信息
		logger.info("查询客服列表 dealerCode:" + code);
		// code = code.trim();
		TrUserEnterprise user = new TrUserEnterprise();
		user.setDealerCode(code);
		// 获取用户信息
		List<TrUserEnterprise> users = wxChatUserService.getList(user);
		users = ChatPolicy.chooseChatUser(users);
		return new Result<List>(1, users, null);
	}

	@ResponseBody
	@RequestMapping(value = "/wx/userInfo", method = { RequestMethod.GET })
	@ApiOperation(value = "客服信息", notes = "查询客服信息")
	public Result<TrUserEnterprise> getWxUser(@RequestParam(value = "weixinCode", required = true) String weixinCode) {
		// 根据客服id获取客服信息
		logger.info("根据客服id获取客服信息:" + weixinCode);
		TrUserEnterprise user = new TrUserEnterprise();
		user.setWxUserId(weixinCode);
		// 获取用户信息
		user = wxChatUserService.getOne(user);

		if (user == null) {
			return new Result(10012, null, "no user!");
		}
		return new Result<TrUserEnterprise>(1, user, null);

	}

	@ResponseBody
	@RequestMapping(value = "/wx/dealerInfo", method = { RequestMethod.GET })
	@ApiOperation(value = "销售店信息", notes = "获取销售店信息")
	public Result<TmDealer> getTmDealer(@RequestParam(value = "dealerCode", required = true) String dealerCode) {
		logger.info("根据销售店id获取销售店信息:" + dealerCode);
		TmDealer dealer = new TmDealer();
		dealer.setDealerCode(dealerCode);
		dealer = dealerService.getOne(dealer);
		if (dealer == null) {
			return new Result(10012, null, "no dealer!");
		}
		return new Result<TmDealer>(1, dealer, null);
	}

	@ResponseBody
	@RequestMapping(value = "/owner/jcode", method = { RequestMethod.GET })
	@ApiOperation(value = "查询车主jmessage账号", notes = "查询车主jmessage账号")
	public Result<Map> getOwnerJmessageCode(@RequestParam(value = "ownerCode", required = true) String ownerCode) {
		// 车主的账号
		logger.info("查询车主jmessage账号 ownerCode:" + ownerCode);
		TmCarOwner owner = new TmCarOwner();
		owner.setPhone(ownerCode);
		owner = ownerService.getOne(owner);

		if (owner == null) {
			return new Result(10012, null, null);
		}
		// 是否有jmessageCode
		if (owner.getJmessageCode() == null || owner.getJmessageCode().trim().equals("")) {
			// 没有则将车主账号注册
			Result<Map> regResult = userOperator.registerAdmins(ownerCode, ChatConstant.JMESSAGE_DEFAULT_PWD);
			if (regResult.getReturnFlag() != 1) {// 注册失败
				return regResult;
			}
			// 修改数据库
			owner.setJmessageCode(ownerCode);
			if (ownerService.updateOwner(owner) <= 0) {
				return new Result(10013, null, null);
			}

		} else {
			Result<Map> regResult = userOperator.getUserInfo(ownerCode);
			if (regResult == null || regResult.getReturnFlag() != 1) {// 不存在
				regResult = userOperator.registerAdmins(ownerCode, ChatConstant.JMESSAGE_DEFAULT_PWD);
				if (regResult.getReturnFlag() != 1) {// 注册失败
					return regResult;
				}
				// 修改数据库
				owner.setJmessageCode(ownerCode);
				if (ownerService.updateOwner(owner) <= 0) {
					return new Result(10013, null, null);
				}
			}

		}

		// 返回车主jmessageCode
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("code", ownerCode);
		map.put("password", ChatConstant.JMESSAGE_DEFAULT_PWD);
		return new Result<Map>(1, map, null);

	}

	@ResponseBody
	@RequestMapping(value = "/message", method = { RequestMethod.POST })
	@ApiOperation(value = "发送消息", notes = "app用户向微信客服推送文本消息")
	public Result<Map> message(@RequestBody Map<String, Object> params
	// @RequestParam(value = "ownerCode", required = true) String ownerCode,
	// @RequestParam(value = "wxUserCode", required = true) String wxUserCode,
	// @RequestParam(value = "chatContent", required = true) String chatContent
	) {
		String ownerCode = (String) params.get("ownerCode");
		String wxUserCode = (String) params.get("wxUserCode");
		String chatContent = (String) params.get("chatContent");
		logger.info("发送信息接口:ownerCode:" + ownerCode + " wxUserCode:" + wxUserCode + " chatContent:" + chatContent);
		// 获得各个参数

		// 根据wxUsserCode获取客服信息
		TrUserEnterprise wxChatUser = new TrUserEnterprise();
		wxChatUser.setWxUserId(wxUserCode);
		wxChatUser = wxChatUserService.getOne(wxChatUser);
		if (wxChatUser == null) {
			return new Result(10021, null, "no wx user!");
		}

		TmCarOwner owner = new TmCarOwner();
		owner.setPhone(ownerCode);// 使用电话做code
		owner = ownerService.getOne(owner);

		if (owner == null) {
			return new Result(10022, null, "no app user!");
		}
		if (owner.getJmessageCode() == null || owner.getJmessageCode().trim().equals("")) {
			return new Result(10022, null, "app user need jmessagecode!");
		}
		Result<Map> rtn = null;
		synchronized (ownerCode.intern()) {
			rtn = messageService.app2WxTransaction(wxChatUser, owner, chatContent);
		}

		if (rtn == null) { //
			rtn = new Result<Map>(ChatConstant.RESULT_RETURN_FLAG_DB, null, null);
		}
		if (rtn.getReturnFlag() == 1) {// 发送通知
			// 判断是否在线
			Boolean onlineFlag = null;
			Result<Map> onlineResult = userOperator.getUserState(wxChatUser.getJmessageCode());
			if (onlineResult.getReturnFlag() == 1 && onlineResult.getData() != null) {
				onlineFlag = (Boolean) onlineResult.getData().get("online");
			}
			// 通过微信发送通知
			// 获取token
			WxToken token = wxService.getWxToken();
			// 推送通知
			// (String token,String userId,int agentId,String content)
			if (chatContent.startsWith("@" + commonProperties.getAppkey())) {
				chatContent = chatContent.substring(("@" + commonProperties.getAppkey()).length());
			}
			// commonProperties.getAppkey()
			WxMsgSend userInfo = WxUtil.sendWxMsg(token.getAccessToken(), wxChatUser.getWxUserId(),
					commonProperties.agentId, chatContent);

		}
		// 神策发送消息
		// try {
		// Map<String, Object> properties = new HashMap<String, Object>();
		// // 客服类型 销售客服/售后客服
		// properties.put("serviceType", wxChatUser.getDealerCsType() == 0 ? "销售客服" :
		// "售后客服");
		// // 发送方（用户，客服）
		// properties.put("sender", "用户");
		// // 销售店名称
		// properties.put("dealer_name", wxChatUser.getDealerName());
		// // 销售店code
		// properties.put("dealer_code", wxChatUser.getDealerCode());
		// SensorsAnalyInit.sa.track(owner.getUserId().toString(), true,
		// "OnlineConsultationService", properties);
		// } catch (Exception e) {
		// logger.error("<messagePush>神策埋线发生异常：", e);
		// }
		return rtn;
	}

	@ResponseBody
	@RequestMapping(value = "/file", method = RequestMethod.POST)
	// public Result<Map> uploadFile(HttpServletRequest request) {
	@ApiOperation(value = "上传图片", notes = "上传聊天图片返回url地址")
	public Result<Map> uploadFile(@RequestParam(value = "file", required = true) MultipartFile file) {

		logger.info("上传文件:uploadFile:");

		// List<MultipartFile> files = ((MultipartHttpServletRequest)
		// request).getFiles("imgFile");
		// MultipartFile file = files.get(0);
		Result<Map> rtn = null;
		try {
			// logger.debug("type:" + file.getContentType());
			// logger.debug("name:" + file.getName());
			// logger.debug("oname:" + file.getOriginalFilename());
			logger.debug("size:" + file.getSize());
			// logger.debug(file.getBytes().toString());

			// file.transferTo(targetFile);

			// String fileId = FileStore.getInstance().write(null, null,
			// file.getOriginalFilename(), file.getBytes());
			String name = DateUtil.format(new Date(), "HHmmssSSS") + RandomNum.createRandomString(6) + ".jpg";
			String fileId = FileStore.getInstance().write("nd02", "fs01", name, file.getBytes());
			logger.debug("fileId = " + fileId);
			// String fileUrl = FileStore.getInstance().getDomainURL(fileId);
			// logger.debug("fileUrl = " + fileUrl);
			Map map = new HashMap();
			map.put("url", fileId);
			rtn = new Result(1, map, null);
		} catch (FileStoreException e) {
			logger.error("FileStore is failure.", e);
			rtn = new Result(100031, null, "filestore failure");
		} catch (IOException e) {
			logger.error("FileStore have io error!.", e);
			rtn = new Result(100032, null, "io failure");
		} catch (Exception e) {
			logger.error("error:", e);
			rtn = new Result(100033, null, "io failure");
		}

		return rtn;
	}

	@ResponseBody
	@RequestMapping(value = "/videoFile", method = RequestMethod.POST)
	// public Result<Map> uploadFile(HttpServletRequest request) {
	@ApiOperation(value = "上传常见内容视频", notes = "上传永久视频素材返回url地址和mediaId")
	public Result<Map> uploadPermanentVideoFile(@RequestParam(value = "file", required = true) MultipartFile file) {

		logger.info("上传文件:uploadFile:");

		Result<Map> rtn = null;
		try {
			logger.debug("size:" + file.getSize());
			// 视频素材最大10M
			if (file.getSize() > 10 * 1024) {
				return new Result(100034, null, "聊天视频文件不得大于10MB,且仅支持mp4格式");
			}
			String name = DateUtil.format(new Date(), "HHmmssSSS") + RandomNum.createRandomString(6) + ".mp4";
			String fileId = FileStore.getInstance().write("nd02", "fs01", name, file.getBytes());
			logger.debug("fileId = " + fileId);
			// 上传视频文件到微信永久素材

			Map map = new HashMap();
			map.put("url", fileId);
			rtn = new Result(1, map, null);
		} catch (FileStoreException e) {
			logger.error("FileStore is failure.", e);
			rtn = new Result(100031, null, "filestore failure");
		} catch (IOException e) {
			logger.error("FileStore have io error!.", e);
			rtn = new Result(100032, null, "io failure");
		} catch (Exception e) {
			logger.error("error:", e);
			rtn = new Result(100033, null, "io failure");
		}

		return rtn;
	}

	@RequestMapping(value = "/logs", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "获取聊天记录", notes = "获取聊天记录")
	public Result<List<Map<String, Object>>> wxChatLogs(
			@RequestParam(value = "pageCurrent", required = false) Integer pageCurrent,
			@RequestParam(value = "pageSize", required = false) Integer pageSize,
			@RequestParam(value = "startDay", required = false) String startDay, // 开始时间
			@RequestParam(value = "endDay", required = false) String endDay, // 结束时间
			@RequestParam(value = "csType", required = false) Integer csType, // 销售种类
			@RequestParam(value = "ownerCode", required = false) String ownerCode, // app用户
			@RequestParam(value = "userName", required = false) String userName, // 客服名字
			@RequestParam(value = "userId", required = false) String userIdLk,
			@RequestParam(value = "dealerCodes", required = false) String dealerCodes,
			@RequestParam(value = "sortField", required = false) String sortField,
			@RequestParam(value = "orderType", required = false) String orderType) {// 客服id
		logger.info("获取聊天详情:wxChatLogs " + ownerCode + " " + csType + " " + userName + " " + userIdLk + " " + startDay
				+ " " + endDay + " " + pageCurrent + " " + pageSize);
		String userId = wxChatUserService.getChatUserIdByLKUserId(Integer.valueOf(userIdLk)).toString();
		List<String> dealerCodesList = null;
		if (dealerCodes != null && !dealerCodes.trim().equals("")) {
			// codes.split(",");
			dealerCodesList = Arrays.asList(dealerCodes.split(","));
		}

		List<String> ownerCodeList = null;
		if (ownerCode != null && !ownerCode.trim().equals("")) {
			// codes.split(",");
			ownerCodeList = Arrays.asList(ownerCode.split(","));
		}

		if (pageCurrent != null && pageSize != null) {
			PageHelper.startPage(pageCurrent, pageSize);
		}

		if (userName != null) {
			try {
				userName = URLDecoder.decode(userName, "UTF-8");
			} catch (Exception ex) {
				logger.error("", ex);
			}
		}

		List<Map<String, Object>> list = wxUserService.getWxChatLog(userId, userName, ownerCodeList, csType, startDay,
				endDay, dealerCodesList, sortField, orderType, null, null);
		PageInfo<Map<String, Object>> pageInfo = new PageInfo<Map<String, Object>>(list);
		return new Result(new Long(pageInfo.getTotal()).intValue(), list, null);
	}

	@RequestMapping(value = "/userowners", method = { RequestMethod.POST, RequestMethod.GET })
	@ResponseBody
	@ApiOperation(value = "获取客服聊天对应", notes = "获取客服聊天对应记录")
	public Result<List<Map<String, Object>>> wxChatOwners(
			@RequestParam(value = "pageCurrent", required = false) Integer pageCurrent,
			@RequestParam(value = "pageSize", required = false) Integer pageSize,
			@RequestParam(value = "ownerCode", required = false) String ownerCode,
			@RequestParam(value = "modelPhones", required = false) String modelPhones,
			@RequestParam(value = "ownerName", required = false) String ownerName,
			@RequestParam(value = "csType", required = false) Integer csType,
			@RequestParam(value = "dealerCodes", required = false) String dealerCodes,
			@RequestParam(value = "sortField", required = false) String sortField,
			@RequestParam(value = "orderType", required = false) String orderType) {
		logger.info("获取客服聊天对应" + ownerCode + " " + modelPhones + " " + csType + " " + dealerCodes + " " + pageCurrent
				+ " " + pageSize);

		List<String> dealerCodesList = null;
		if (dealerCodes != null && !dealerCodes.trim().equals("")) {
			// codes.split(",");
			dealerCodesList = Arrays.asList(dealerCodes.split(","));
		}

		List<String> ownerCodeList = null;
		if (ownerCode != null && !ownerCode.trim().equals("")) {
			// codes.split(",");
			ownerCodeList = Arrays.asList(ownerCode.split(","));
		}
		List<String> modelPhoneList = null;
		if (modelPhones != null && !modelPhones.trim().equals("")) {
			modelPhoneList = Arrays.asList(modelPhones.split(","));
		}

		// PageHelper.startPage(1, 5);
		if (pageCurrent != null && pageSize != null) {
			PageHelper.startPage(pageCurrent, pageSize);
		}

		if (ownerName != null) {
			try {
				ownerName = URLDecoder.decode(ownerName, "UTF-8");
			} catch (Exception ex) {
				logger.error("", ex);
			}

		}
		List<Map<String, Object>> list = wxUserService.getUserOwnerList(dealerCodesList, ownerCodeList, modelPhoneList,
				csType, ownerName, sortField, orderType, null, null);
		// System.out.println("list.size: "+ list.size());
		PageInfo<Map<String, Object>> pageInfo = new PageInfo<Map<String, Object>>(list);

		// pageInfo.getSize();
		// System.out.println("pageInfo.size: "+ pageInfo.getSize() + " " +
		// pageInfo.getTotal() + " "
		// + pageInfo.getPageNum() + " " + pageInfo.getLastPage());
		// List<Map<String, Object>> list = wxUserService.getWxChatLog(userId,
		// ownerCode, pageCurrent, pageSize);
		return new Result(new Long(pageInfo.getTotal()).intValue(), list, null);
	}

	@RequestMapping(value = "/logs", method = RequestMethod.DELETE)
	@ResponseBody
	@ApiOperation(value = "删除log", notes = "删除log")
	public Result<Map> cleanLogs(@RequestParam(value = "cleanDate", required = true) String cleanDate) {
		// Map<String, Object> map = new HashMap<String, Object>();
		// map.put("cleanDate", cleanDate);
		// int rtn = wxChatLogMapper.deleteExpire(map);
		int delNum = wxChatLogMapper.deleteLog(cleanDate);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("delNum", delNum);
		return new Result(1, map, null);
	}

	@RequestMapping(value = "/delLogs", method = { RequestMethod.POST })
	@ResponseBody
	@ApiOperation(value = "删除在线聊天日志", notes = "删除在线聊天日志")
	public Map cleanChatLogs() {
		int days = ChatConstant.LOG_EXPIRE_DAYS;

		int delNum = wxChatLogMapper.deleteExpire(days);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("result", "OK");
		return map;
	}

	// @RequestMapping(value = "/userownerspage", method = RequestMethod.GET)
	// @ResponseBody
	// @ApiOperation(value = "获取客服聊天对应", notes = "获取客服聊天对应记录")
	// public PageInfo<Map<String, Object>> wxChatOwnersPage(
	// @RequestParam(value = "pageCurrent", required = false) Integer
	// pageCurrent,
	// @RequestParam(value = "pageSize", required = false) Integer pageSize,
	// @RequestParam(value = "ownerCode", required = false) String ownerCode,
	// @RequestParam(value = "csType", required = false) Integer csType,
	// @RequestParam(value = "dealerCodes", required = false) String
	// dealerCodes) {
	// logger.info("获取客服聊天对应"+ ownerCode + " " + csType + " " + dealerCodes + "
	// " + pageCurrent + " " + pageSize);
	//
	// List<String> dealerCodesList = null;
	// if(dealerCodes != null){
	// //codes.split(",");
	// dealerCodesList = Arrays.asList(dealerCodes.split(","));
	// }
	//// if(pageCurrent != null && pageSize != null){
	//// PageHelper.startPage(1, 5);
	//// }
	//
	// List<Map<String, Object>> list =
	// wxUserService.getUserOwnerList(dealerCodesList, ownerCode, csType,
	// null,null,pageCurrent, pageSize);
	// System.out.println("list.size: "+ list.size());
	// //if(pageCurrent != null && pageSize != null){
	// PageInfo<Map<String, Object>> pageInfo = new PageInfo<Map<String,
	// Object>>(list);
	// //}
	//
	//
	// //pageInfo.getSize();
	// System.out.println("pageInfo.size: "+ pageInfo.getSize() + " " +
	// pageInfo.getTotal() + " "
	// + pageInfo.getPageNum() + " " + pageInfo.getLastPage());
	// //List<Map<String, Object>> list = wxUserService.getWxChatLog(userId,
	// ownerCode, pageCurrent, pageSize);
	// return pageInfo;
	// }
	@RequestMapping(value = "/wxusers", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "获取客服", notes = "获取客服")
	public Result<List> testGetUser(@RequestParam(value = "codes", required = false) String codes,
			@RequestParam(value = "csType", required = false) Integer csType) {
		logger.info("获取客服");
		List<String> dealerCodes = null;
		if (codes != null) {
			// codes.split(",");
			dealerCodes = Arrays.asList(codes.split(","));
		}
		Map<String, Object> usermap = new HashMap<String, Object>();
		if (csType != null) {
			usermap.put("csType", csType);
			// logger.debug("wuqi!!!!!!!!!!!!!!!!!!! have scType");
		} else {
			// logger.debug("wuqi!!!!!!!!!!!!!!!!!!! have not scType");
		}
		if (dealerCodes != null && dealerCodes.size() > 0) {
			usermap.put("dealerCodes", dealerCodes);
		}
		List<TrUserEnterprise> list = wxChatUserMapper.getWxUserList(usermap);
		// List<Map<String, Object>> list = wxUserService.getWxChatLog(userId,
		// ownerCode, pageCurrent, pageSize);
		return new Result(1, list, null);
	}

	// @RequestMapping(value = "/logs", method = RequestMethod.GET)
	// @ResponseBody
	// @ApiOperation(value = "获取聊天记录", notes = "获取聊天记录")
	// public Result<List<Map<String, Object>>> wxChatLogs(
	// @RequestParam(value = "pageCurrent", required = true) Integer
	// pageCurrent,
	// @RequestParam(value = "pageSize", required = true) Integer pageSize,
	// @RequestParam(value = "ownerCode", required = false) String ownerCode,
	// @RequestParam(value = "userId", required = false) String userId) {
	// logger.info("获取聊天详情:wxChatLogs");
	// List<Map<String, Object>> list = wxUserService.getWxChatLog(userId,
	// ownerCode, pageCurrent, pageSize);
	// return new Result(1, list, null);
	// }

	// @ResponseBody
	// @RequestMapping(value = "/test/bean", method = { RequestMethod.POST })
	// public Result<Map> testBean(User user) {
	// logger.info("测试传递对象:user:" + user.getName() + " :" + user.getPass());
	// Map<String, Object> map = new HashMap<String, Object>();
	// map.put("name", user.getName());
	// map.put("pass", user.getPass());
	// return new Result<Map>(1, map, null);
	//
	// }

	@RequestMapping(value = "/wx/gzMsg", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "接收微信用户发送到公众号的消息", notes = "{\"content\": \"test\",\"fromUserName\": \"omLPIwPJ7ODe15gCSggGJ_g536gE\",\"msgType\":\"text\"}\n *若指定toUserName(后台用户的UserId)，则发送消息给指定客服")
	public Result<String> getWxgzMsg(@RequestBody WxGzMessageDto wxgzMsg) throws Exception {
		// 未完成，这里还需要补充客服删除正在聊天的客户，或者客户发送消息超时之后的客服调度之后的消息发送。当然这个时候，理论上在其他地方，已经正确处理了客服和用户之间的链接，利用最基本的客服选择策略应该可以完成此工作，待测试
		logger.info("获取微信公众号转发的消息:" + wxgzMsg);
		TrUserEnterprise wxChatUser = null;
		TmPotentialUser owner = null ;
		if(StringUtils.isEmpty(wxgzMsg.getToUserName())) {
			// 首先转化openID为userId
			TmPotentialUser queryPuser = new TmPotentialUser();
			queryPuser.setDeviceOpenId(wxgzMsg.getFromUserName());
			owner = tmPotentialUserMapper.selectOne(queryPuser);
			if(owner==null) {
				return new Result(10022, null, "no app user!");
			}
			// 为用户注册极光账号
			if(StringUtils.isEmpty(owner.getJmessageCode())) {
				// 若果没有极光账号，则注册
				Result<Map> regResult = userOperator.registerAdmins(owner.getPotentialUserId().toString(), ChatConstant.JMESSAGE_DEFAULT_PWD);
				if (regResult.getReturnFlag() != 1) {// 注册失败
					logger.error("Jmessage账号注册失败："+owner);
				}else {
					// 修改数据库
					owner.setJmessageCode(owner.getPotentialUserId().toString());
					if (tmPotentialUserMapper.updateByPrimaryKeySelective(owner) <= 0) {
						logger.error("Jmessage账号注册成功，写入数据库失败："+owner);
					}else {
						logger.debug("Jmessage账号注册成功 "+owner);
					}
				}
			}
			logger.debug("策略获取客服:"+owner.getPotentialUserId().toString());
			// 策略获取客服
			wxChatUser = getSuitableChat(owner.getPotentialUserId().toString());
		}else {
			logger.debug("根据指定客服进行沟通链接："+wxgzMsg.getToUserName());
			wxChatUser = wxChatUserService.getChatUserByLKUser(wxgzMsg.getToUserName());
			// 若查询不到指定客服，则沿用客服获取策略获取客服
			if(wxChatUser==null) {
				logger.debug("策略获取客服:"+owner.getPotentialUserId().toString());
				wxChatUser = getSuitableChat(owner.getPotentialUserId().toString());
			}
		}
		logger.debug("客服策略结束："+wxChatUser);
		if(wxChatUser==null) {
			logger.debug("找不到空闲客服，进入客服排队");
			logger.debug("目前没有空闲客服，下面是排队逻辑");
			// 获取所有在线客服
			TrUserEnterprise allInlineChatQuery = new TrUserEnterprise();
			allInlineChatQuery.setJmessageStatus(1);
			List<TrUserEnterprise> allInlineChatList = trUserEnterpriseMapper.select(allInlineChatQuery);
			List<String> waitChats = new ArrayList<String>();
			for(TrUserEnterprise temp : allInlineChatList) {
				waitChats.add(temp.getId().toString());
			}
			ChatMsgDetailDto msgEntity = new ChatMsgDetailDto();
			msgEntity.setFormeUser(owner.getPotentialUserId().toString());
			// 这里如果用户首次发送的消息就是媒体消息，先不要急着上传到服务器， 待得用户真的可以可客服建立链接之后，再做上传操作
			msgEntity.setMsgType(WxMaterialTypeEnum.valueOf(wxgzMsg.getMsgType()));
			msgEntity.setContent(wxgzMsg.getContent());
			msgEntity.setCreateTime(new Date());
			// 初始化可用客服列表
			queueService.setUsefulChats(waitChats);
			Integer waitCode = 1 ;
			if(queueService.addQueue(msgEntity)) {
				waitCode = ChatErrorCode.CHAT_BESY_WAIT ;
			}else {
				waitCode = ChatErrorCode.CHAT_BESY_NEXT ;
			}
			return new Result(waitCode, null, null);
		}
		
		String ownerCode = owner.getPotentialUserId().toString();
		String chatContent = wxgzMsg.getContent();
		String chatContentType = wxgzMsg.getMsgType();
		String title = wxgzMsg.getTitle();
		String url = wxgzMsg.getUrl();
		logger.info("发送信息接口:ownerCode:" + ownerCode + " wxUserCode:" + wxChatUser + " chatContent:"
				+ chatContent+" chatContentType:"+chatContentType);
		// 如果公众号发送过来的是媒体消息，需要先从微信上下载此媒体，然后上传到fileStore，获得媒体url
		if(StringUtils.equals(wxgzMsg.getMsgType(), WxMaterialTypeEnum.image.name()) 
				||StringUtils.equals(wxgzMsg.getMsgType(), WxMaterialTypeEnum.video.name())
				||StringUtils.equals(wxgzMsg.getMsgType(), WxMaterialTypeEnum.voice.name())) {
			chatContent = wxService.getFileUrl(wxgzMsg.getMediaId(),WxMaterialTypeEnum.valueOf(wxgzMsg.getMsgType()),WxMediaFileSourceType.temp).getLocalUrl();
			url = chatContent;
		}
		// 如果是图文，则直接给url
		if(StringUtils.equals(wxgzMsg.getMsgType(), WxMaterialTypeEnum.news.name()) 
				||StringUtils.equals(wxgzMsg.getMsgType(), WxMaterialTypeEnum.mpnews.name())) {
			chatContent = url;
		}
		Result<Map> rtn = null;
		logger.debug("消息整理完成，即将发送消息,发送消息：wxChatUser："+wxChatUser+";owner:"+owner+";chatContent:"+chatContent+";type:"+wxgzMsg.getMsgType());
		synchronized (ownerCode.intern()) {
			rtn = messageService.userToChat(wxChatUser, owner, chatContent,WxMaterialTypeEnum.valueOf(wxgzMsg.getMsgType()),title,url);
		}

		if (rtn == null) { // 发送失败
			rtn = new Result<Map>(ChatErrorCode.MESSAGE_SEND_FAIL, null, null);
		}
//		if (rtn == null) { // 发送失败
//			rtn = new Result<Map>(ChatConstant.RESULT_RETURN_FLAG_DB, null, null);
//		}
		
		// 临时逻辑，待优化：当公众号发来结束语的时候，正常插入消息，然后主动断开聊天链接,以保证断开聊天标示逻辑的正常进行
		if(ChatConstant.ENDSTR.equals(chatContent)) {
			wxController.deleteChatOwner(Integer.parseInt(wxChatUser.getUserId()), owner.getPotentialUserId().toString());
		}
		
		
		// 发送微信通知，此处不需要
//		if (rtn.getReturnFlag() == 1) {// 发送通知
//			// 判断是否在线
//			Boolean onlineFlag = null;
//			Result<Map> onlineResult = userOperator.getUserState(wxChatUser.getJmessageCode());
//			if (onlineResult.getReturnFlag() == 1 && onlineResult.getData() != null) {
//				onlineFlag = (Boolean) onlineResult.getData().get("online");
//			}
//			// 通过微信发送通知
//			// 获取token
//			WxToken token = wxService.getWxToken();
//			// 推送通知
//			// (String token,String userId,int agentId,String content)
//			if (chatContent.startsWith("@" + commonProperties.getAppkey())) {
//				chatContent = chatContent.substring(("@" + commonProperties.getAppkey()).length());
//			}
//			// commonProperties.getAppkey()
//			WxMsgSend userInfo = WxUtil.sendWxMsg(token.getAccessToken(), wxChatUser.getWxUserId(),
//					commonProperties.agentId, chatContent);
//
//		}
		return new Result(ChatErrorCode.SUCCESS, "SUCCESS", null);
	}
	
	/**
	 * 策略获取客服-重构
	 * 1.第一次和客服建立链接，取出所有在线客服，判断客服对应人数是否小于指定值，筛选出在线，且对应人数小于指定值的客服。
	 * 2.若存在条件符合的客服，则随机选出一个，第一次和客服建立链接
	 * 3.若客服均在忙，在缓存中建立队列，【客服-排队序号：用户-用户发送的消息】，或者追加队列。
	 * 4.若队列超出指定的队列深度，则寻找队列深度最浅的客服，追加队列
	 * 5.若所有客服的队列深度均以超过最大值，则返回客服均在忙。
	 * 
	 * 查找对应关系表中，存不存在有效的用户-客服对应关系，有则存在链接，直接返回客服。
	 * 若对应关系中不存在有效的链接，则查找此用户是否已经在某个客服的队列中。 （两个查询维度，且数据更新量大（追加队列，队列更新））
	 * 若对应关系中不存在，且队列中不存在，则排队。
	 * 
	 * 注*：
	 * 1.客服对应关系和队列的建立，在此处。客服对应关系的过期、队列的调整均使用定时任务。
	 * */
	@RequestMapping(value = "/wx/getSuitableChat", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "客服策略测试", notes = "ownerCode")
	public TrUserEnterprise getSuitableChat(@RequestParam("ownerCode") String ownerCode) {
		logger.debug("new 策略获取客服开始：用户："+ownerCode);
		WxUserOwner usefulConnectQuery = new WxUserOwner();
		usefulConnectQuery.setOwnerCode(ownerCode);
		usefulConnectQuery.setStatus(WxUserOwner.STATUS_USEFUL);
		WxUserOwner useFulConnect = wxUserService.getOne(usefulConnectQuery);
		logger.debug("new 首先检查此用户在客服对应关系表中是否存在有效链接:"+useFulConnect);
		if(useFulConnect!=null) {
			return wxUserService.getWxChatUser(useFulConnect.getWxUserId());
		}
		logger.debug("new 不存在有效链接，则获取所有在线客服");
		TrUserEnterprise allInlineChatQuery = new TrUserEnterprise();
		allInlineChatQuery.setJmessageStatus(1);
		List<TrUserEnterprise> allInlineChatList = trUserEnterpriseMapper.select(allInlineChatQuery);
		logger.debug("new 获取所有在线状态的客服"+allInlineChatList);
		if(CollectionUtils.isEmpty(allInlineChatList)) {
			logger.debug("new 目前没有在线状态的客服");
			return null;
		}
		List<String> leisurestChatIds = wxUserService.getLeisurestChat(allInlineChatList);	
		logger.debug("获取空闲客服列表结果："+leisurestChatIds);
		if(CollectionUtils.isEmpty(leisurestChatIds)) {
			logger.debug("new 目前没有空闲的在线服");
			return null;
		}
		TrUserEnterprise leisurestChat = trUserEnterpriseMapper.selectByPrimaryKey(new BigDecimal(leisurestChatIds.get(0))) ;
		logger.debug("new 根据空闲客服计算结果，查询所有的在线客中，对应人数最少的客服"+leisurestChat);
		if(leisurestChat!=null) {
			return leisurestChat;
		}
		return null;
//		logger.debug("策略获取客服开始：用户："+ownerCode);
//		// 1.首先判断当前用户，当天有没有已经存在的客服
//		TrUserEnterprise wxChatUser = null ;
//		Date currentDate = DateUtil.getCurrentDate(DateUtil.FORMAT_SIMPLE_PATTERN);
//		Map<String,Object> queryChatParam = new HashMap<String,Object>();
//		queryChatParam.put("lastStartTime", currentDate);
//		queryChatParam.put("ownerCode", ownerCode);// 使用用户的openId作为消息传递的唯一表示
//		List<Map<String,Object>> charUsers = wxUserOwnerMapper.getLeisureService(queryChatParam);
//		logger.debug("和"+ownerCode+"链接中的客服："+charUsers);
//		if(CollectionUtils.isEmpty(charUsers)) {
//			// 2.若不存在，则修改查询条件，获取当天的客服已经对应人数列表，按照对应人数从小到大的顺序排序
//			queryChatParam.remove("ownerCode");
//			charUsers = wxUserOwnerMapper.getLeisureService(queryChatParam);
//			// 由于客服表和客服用户对应表不在同一个数据源中，所以，这里取出的仅仅是已经存在于对应关系表中的客服
//			logger.debug("遍历对应表中对应的所有客服："+(charUsers==null ? 0 : charUsers.size()));
//			// 如果查询到的客服人员对应为空 || 如果对应人数最少的客服的对应人数不为0
//			if(CollectionUtils.isEmpty(charUsers) || !StringUtils.equals(charUsers.get(0).get("SCOUNT").toString(), "0")) {
//				// 获取所有的客服
//				List<TrUserEnterprise> allChat = trUserEnterpriseMapper.selectAll();
//				List<String> chats = new ArrayList<String>();
//				// 对全部客服进行遍历，若已经存在对应关系的客服
//				for(TrUserEnterprise tempChat : allChat) {
//					boolean isContain = false;
//					for(Map<String,Object> tempChatId : charUsers) {
//						// 在不同数据源的客服表和客服用户对应表的关系中，客服表的userId为林肯后台系统的唯一标示，客服表的ID为客服的唯一标识
//						// 客服用户对应表中，wx_user_id为客服ID，对应的是客服表的主键ID
//						// 未完成，此处ID关联冗余，完全可以通用林肯后台用户的userId为客服的唯一标示 ，后续做优化
//						if(StringUtils.equals(tempChatId.get("WX_USER_ID").toString(), tempChat.getId().toString())) {
//							isContain = true ;
//							break;
//						}
//					}
//					// 如果此客服不在对应表中，则表明客服还未和任何用户沟通过，则使用此客服
//					if(!isContain) {
//						logger.debug("从客服表中拿出不存在于对应表中的客服："+tempChat);
//						wxChatUser = tempChat;
//						break;
//					}
//				}
//				logger.debug("从所有客服中随机获取客服："+wxChatUser);
//			}else {
//				wxChatUser = wxUserService.getWxChatUser(String.valueOf(charUsers.get(0).get("WX_USER_ID")));
//			}
//		}
//		if(wxChatUser==null) {
//			// 若存在对应客服，则直接使用 ，不存在，则获取对应人数最少的客服，若当天无工作客服，则随机获取客服
//			wxChatUser = wxUserService.getWxChatUser(String.valueOf(charUsers.get(0).get("WX_USER_ID")));
//		}
//		logger.debug("策略获取客服结束，获取客服为："+wxChatUser);
//		return wxChatUser;
	}
	
	@RequestMapping(value = "/wx/queryChatWaitQueue", method = RequestMethod.POST)
	@ResponseBody
	@ApiOperation(value = "客服排队测试", notes = "chatId=3")
	public void queryChatWaitQueue(@RequestParam(value = "chatId", required = false) String chatId) {
		if(chatId!=null) {
			queueService.printChatQueue(chatId);
		}else {
			queueService.printAllQueue();
		}
	}
	
	@RequestMapping(value = "/wx/resetChatWaitQueue", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "测试清理队列内容", notes = "清理等待队列")
	public void resetChatWaitQueue(){
		queueService.setUsefulChats(new ArrayList<String>());
	}
}